home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / aptdaemon / gtkwidgets.py < prev    next >
Text File  |  2009-10-14  |  23KB  |  603 lines

  1. """
  2. This module provides widgets to use aptdaemon in a GTK application.
  3. """
  4. # Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de>
  5. #
  6. # Licensed under the GNU General Public License Version 2
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program; if not, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  
  22. __author__ = "Sebastian Heinlein <devel@glatzor.de>"
  23.  
  24. from gettext import gettext as _
  25. import os
  26. import pty
  27.  
  28. import apt_pkg
  29. import dbus
  30. import dbus.mainloop.glib
  31. import gobject
  32. import gtk
  33. import pango
  34. import pygtk
  35. import vte
  36.  
  37. import client
  38. from enums import *
  39.  
  40. dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
  41.  
  42. (COLUMN_ID,
  43.  COLUMN_PACKAGE) = range(2)
  44.  
  45.  
  46. class AptStatusIcon(gtk.Image):
  47.     """
  48.     Provides a gtk.Image which shows an icon representing the status of a
  49.     aptdaemon transaction
  50.     """
  51.     def __init__(self, transaction=None, size=gtk.ICON_SIZE_DIALOG):
  52.         gtk.Image.__init__(self)
  53.         self.icon_size = size
  54.         self.icon_name = None
  55.         self._signals = []
  56.         self.set_alignment(0, 0)
  57.         if transaction != None:
  58.             self.set_transaction(transaction)
  59.  
  60.     def set_transaction(self, transaction):
  61.         """Connect to the given transaction"""
  62.         for sig in self._signals:
  63.             gobject.source_remove(sig)
  64.         self._signals = []
  65.         self._signals.append(
  66.             transaction.connect("status", self._on_status_changed))
  67.  
  68.     def set_icon_size(self, size):
  69.         """Set the icon size to gtk stock icon size value"""
  70.         self.icon_size = size
  71.  
  72.     def _on_status_changed(self, transaction, status):
  73.         """Set the status icon according to the changed status"""
  74.         icon_name = get_status_icon_name_from_enum(status)
  75.         if icon_name is None:
  76.             icon_name = gtk.STOCK_MISSING_IMAGE
  77.         if icon_name != self.icon_name:
  78.             self.set_from_icon_name(icon_name, self.icon_size)
  79.             self.icon_name = icon_name
  80.  
  81.  
  82. class AptRoleIcon(AptStatusIcon):
  83.     """
  84.     Provides a gtk.Image which shows an icon representing the role of an
  85.     aptdaemon transaction
  86.     """
  87.     def set_transaction(self, transaction):
  88.         for sig in self._signals:
  89.             gobject.source_remove(sig)
  90.         self._signals = []
  91.         self._signals.append(
  92.             transaction.connect("role", self._on_role_changed))
  93.  
  94.     def _on_role_changed(self, transaction, role_enum):
  95.         """Show an icon representing the role"""
  96.         icon_name = get_role_icon_name_from_enum(role_enum)
  97.         if icon_name is None:
  98.             icon_name = gtk.STOCK_MISSING_IMAGE
  99.         if icon_name != self.icon_name:
  100.             self.set_from_icon_name(icon_name, self.icon_size)
  101.             self.icon_name = icon_name
  102.  
  103.  
  104. class AptStatusAnimation(AptStatusIcon):
  105.     """
  106.     Provides a gtk.Image which shows an animation representing the 
  107.     transaction status
  108.     """
  109.     def __init__(self, transaction=None, size=gtk.ICON_SIZE_DIALOG):
  110.         AptStatusIcon.__init__(self, transaction, size)
  111.         self.animation = []
  112.         self.ticker = 0
  113.         self.frame_counter = 0
  114.         self.iter = 0
  115.         name = get_status_animation_name_from_enum(STATUS_WAITING)
  116.         fallback = get_status_icon_name_from_enum(STATUS_WAITING)
  117.         self.set_animation(name, fallback)
  118.  
  119.     def set_animation(self, name, fallback=None, size=None):
  120.         """Show and start the animation of the given name and size"""
  121.         if name == self.icon_name:
  122.             return
  123.         if size is not None:
  124.             self.icon_size = size
  125.         self.stop_animation()
  126.         animation = []
  127.         (width, height) = gtk.icon_size_lookup(self.icon_size)
  128.         theme = gtk.icon_theme_get_default()
  129.         if name is not None and theme.has_icon(name):
  130.             pixbuf = theme.load_icon(name, width, 0)
  131.             rows = pixbuf.get_height() / height
  132.             cols = pixbuf.get_width() / width
  133.             for r in range(rows):
  134.                 for c in range(cols):
  135.                     animation.append(pixbuf.subpixbuf(c * width, r * height, 
  136.                                                       width, height))
  137.             if len(animation) > 0:
  138.                 self.animation = animation
  139.                 self.iter = 0
  140.                 self.set_from_pixbuf(self.animation[0])
  141.                 self.start_animation()
  142.             else:
  143.                 self.set_from_pixbuf(pixbuf)
  144.             self.icon_name = name
  145.         elif fallback is not None and theme.has_icon(fallback):
  146.             self.set_from_icon_name(fallback, self.icon_size)
  147.             self.icon_name = fallback
  148.         else:
  149.             self.set_from_icon_name(gtk.STOCK_MISSING_IMAGE)
  150.  
  151.     def start_animation(self):
  152.         """Start the animation"""
  153.         if self.ticker == 0:
  154.             self.ticker = gobject.timeout_add(200, self._advance)
  155.  
  156.     def stop_animation(self):
  157.         """Stop the animation"""
  158.         if self.ticker != 0:
  159.             gobject.source_remove(self.ticker)
  160.             self.ticker = 0
  161.  
  162.     def _advance(self):
  163.         """
  164.         Show the next frame of the animation and stop the animation if the
  165.         widget is no longer visible
  166.         """
  167.         if self.get_property("visible") == False:
  168.             self.ticker = 0
  169.             return False
  170.         self.iter = self.iter + 1
  171.         if self.iter >= len(self.animation):
  172.             self.iter = 0
  173.         self.set_from_pixbuf(self.animation[self.iter])
  174.         return True
  175.  
  176.     def _on_status_changed(self, transaction, status):
  177.         """
  178.         Set the animation according to the changed status
  179.         """
  180.         name = get_status_animation_name_from_enum(status)
  181.         fallback = get_status_icon_name_from_enum(status)
  182.         self.set_animation(name, fallback)
  183.  
  184.  
  185. class AptRoleLabel(gtk.Label):
  186.     """
  187.     Status label for the running aptdaemon transaction
  188.     """
  189.     def __init__(self, transaction=None):
  190.         gtk.Label.__init__(self)
  191.         self.set_alignment(0, 0)
  192.         self.set_ellipsize(pango.ELLIPSIZE_END)
  193.         self._signals = []
  194.         if transaction != None:
  195.             self.set_transaction(transaction)
  196.  
  197.     def set_transaction(self, transaction):
  198.         """Connect the status label to the given aptdaemon transaction"""
  199.         for sig in self._signals:
  200.             gobject.source_remove(sig)
  201.         self._signals = []
  202.         self._signals.append(transaction.connect("role", self._on_role_changed))
  203.  
  204.     def _on_role_changed(self, transaction, role):
  205.         """Set the role text."""
  206.         self.set_markup(get_role_localised_present_from_enum(role))
  207.  
  208.  
  209. class AptStatusLabel(gtk.Label):
  210.     """
  211.     Status label for the running aptdaemon transaction
  212.     """
  213.     def __init__(self, transaction=None):
  214.         gtk.Label.__init__(self)
  215.         self.set_alignment(0, 0)
  216.         self.set_ellipsize(pango.ELLIPSIZE_END)
  217.         self._signals = []
  218.         if transaction != None:
  219.             self.set_transaction(transaction)
  220.  
  221.     def set_transaction(self, transaction):
  222.         """Connect the status label to the given aptdaemon transaction"""
  223.         for sig in self._signals:
  224.             gobject.source_remove(sig)
  225.         self._signals = []
  226.         self._signals.append(
  227.             transaction.connect("status", self._on_status_changed))
  228.         self._signals.append(
  229.             transaction.connect("status-details",
  230.                                 self._on_status_details_changed))
  231.  
  232.     def _on_status_changed(self, transaction, status):
  233.         """Set the status text according to the changed status"""
  234.         self.set_markup("<i>%s</i>" % get_status_string_from_enum(status))
  235.  
  236.     def _on_status_details_changed(self, transaction, text):
  237.         """Set the status text to the one reported by apt"""
  238.         self.set_markup("<i>%s</i>" % text)
  239.  
  240.  
  241. class AptProgressBar(gtk.ProgressBar):
  242.     """
  243.     Provides a gtk.Progress which represents the progress of an aptdaemon
  244.     transactions
  245.     """
  246.     def __init__(self, transaction=None):
  247.         gtk.ProgressBar.__init__(self)
  248.         self.set_ellipsize(pango.ELLIPSIZE_END)
  249.         self.set_text(" ")
  250.         self.set_pulse_step(0.05)
  251.         self._signals = []
  252.         if transaction != None:
  253.             self.set_transaction(transaction)
  254.  
  255.     def set_transaction(self, transaction):
  256.         """Connect the progress bar to the given aptdaemon transaction"""
  257.         for sig in self._signals:
  258.             gobject.source_remove(sig)
  259.         self._signals = []
  260.         self._signals.append(
  261.             transaction.connect("finished", self._on_finished))
  262.         self._signals.append(
  263.             transaction.connect("progress", self._on_progress_changed))
  264.         self._signals.append(
  265.             transaction.connect("progress-details", self._on_progress_details))
  266.  
  267.     def _on_progress_changed(self, transaction, progress):
  268.         """
  269.         Update the progress according to the latest progress information
  270.         """
  271.         if progress > 100:
  272.             self.pulse()
  273.         else:
  274.             self.set_fraction(progress/100.0)
  275.  
  276.     def _on_progress_details(self, transaction, items_done, items_total,
  277.                              bytes_done, bytes_total, speed, eta):
  278.         """
  279.         Update the progress bar text according to the latest progress details
  280.         """
  281.         if items_total == 0 and bytes_total == 0:
  282.             self.set_text(" ")
  283.             return
  284.         if speed != 0:
  285.             self.set_text(_("Downloaded %sB of %sB "
  286.                             "at %sB/s") % (apt_pkg.SizeToStr(bytes_done),
  287.                                           apt_pkg.SizeToStr(bytes_total),
  288.                                           apt_pkg.SizeToStr(speed)))
  289.         else:
  290.             self.set_text(_("Downloaded %sB "
  291.                             "of %sB") % (apt_pkg.SizeToStr(bytes_done),
  292.                                          apt_pkg.SizeToStr(bytes_total)))
  293.  
  294.     def _on_finished(self, transaction, exit):
  295.         """Set the progress to 100% when the transaction is complete"""
  296.         self.set_fraction(1)
  297.  
  298. class AptTerminalExpander(gtk.Expander):
  299.     def __init__(self, transaction=None):
  300.         gtk.Expander.__init__(self, _("Details"))
  301.         self._signals = []
  302.         self.set_sensitive(False)
  303.         self.set_expanded(False)
  304.         self.terminal = AptTerminal()
  305.         self.add(self.terminal)
  306.         if transaction != None:
  307.             self.set_transaction(transaction)
  308.  
  309.     def set_transaction(self, transaction):
  310.         """Connect the status label to the given aptdaemon transaction"""
  311.         for sig in self._signals:
  312.             gobject.source_remove(sig)
  313.         self._signals.append(
  314.                 transaction.connect("allow_terminal",
  315.                                     self._on_allow_terminal))
  316.         self.terminal.set_transaction(transaction)
  317.  
  318.     def _on_allow_terminal(self, transaction, allow_terminal):
  319.         """
  320.         Connect the terminal to the pty device
  321.         """
  322.         if allow_terminal == True:
  323.             self.set_sensitive(True)
  324.  
  325. class AptTerminal(vte.Terminal):
  326.     def __init__(self, transaction=None):
  327.         vte.Terminal.__init__(self)
  328.         self._signals = []
  329.         self._master, self._slave = pty.openpty()
  330.         self._ttyname = os.ttyname(self._slave)
  331.         self.set_size(80, 24)
  332.         self.set_pty(self._master)
  333.         if transaction != None:
  334.             self.set_transaction(transaction)
  335.  
  336.     def set_transaction(self, transaction):
  337.         """Connect the status label to the given aptdaemon transaction"""
  338.         for sig in self._signals:
  339.             gobject.source_remove(sig)
  340.         self._signals.append(
  341.                 transaction.connect("allow-terminal",
  342.                                     self._on_allow_terminal))
  343.         self._transaction = transaction
  344.         self._transaction.set_terminal(self._ttyname)
  345.  
  346.     def _on_allow_terminal(self, transaction, allow_terminal):
  347.         """
  348.         Show the terminal
  349.         """
  350.         self.set_sensitive(allow_terminal)
  351.  
  352. class AptCancelButton(gtk.Button):
  353.     """
  354.     Provides a gtk.Button which allows to cancel a running aptdaemon
  355.     transaction
  356.     """
  357.     def __init__(self, transaction):
  358.         gtk.Button.__init__(self, stock=gtk.STOCK_CANCEL)
  359.         self.set_sensitive(True)
  360.         self._signals = []
  361.         if transaction != None:
  362.             self.set_transaction(transaction)
  363.  
  364.     def set_transaction(self, transaction):
  365.         """Connect the status label to the given aptdaemon transaction"""
  366.         for sig in self._signals:
  367.             gobject.source_remove(sig)
  368.         self._signals = []
  369.         self._signals.append(
  370.                 transaction.connect("finished", self._on_finished))
  371.         self._signals.append(
  372.                 transaction.connect("allow-cancel",
  373.                                     self._on_allow_cancel_changed))
  374.         self.connect("clicked", self._on_clicked, transaction)
  375.  
  376.     def _on_allow_cancel_changed(self, transaction, allow_cancel):
  377.         """
  378.         Enable the button if cancel is allowed and disable it in the other case
  379.         """
  380.         self.set_sensitive(allow_cancel)
  381.  
  382.     def _on_finished(self, transaction, status):
  383.         self.set_sensitive(False)
  384.  
  385.     def _on_clicked(self, button, transaction):
  386.         transaction.cancel()
  387.         self.set_sensitive(False)
  388.  
  389.  
  390. class AptProgressDialog(gtk.Dialog):
  391.     """
  392.     Complete progress dialog for long taking aptdaemon transactions, which
  393.     features a progress bar, cancel button, status icon and label
  394.     """
  395.     def __init__(self, transaction=None, parent=None, terminal=True,
  396.                  debconf=True):
  397.         gtk.Dialog.__init__(self, buttons=None, parent=parent)
  398.         self.debconf = debconf
  399.         # Setup the dialog
  400.         self.set_border_width(6)
  401.         self.set_has_separator(False)
  402.         #self.set_resizable(False)
  403.         self.vbox.set_spacing(6)
  404.         # Setup the cancel button
  405.         self.button_cancel = AptCancelButton(transaction)
  406.         self.action_area.pack_start(self.button_cancel, False, False, 0)
  407.         # Setup the status icon, label and progressbar
  408.         hbox = gtk.HBox()
  409.         hbox.set_spacing(12)
  410.         hbox.set_border_width(6)
  411.         self.icon = AptRoleIcon()
  412.         hbox.pack_start(self.icon, False, True, 0)
  413.         vbox = gtk.VBox()
  414.         vbox.set_spacing(12)
  415.         self.label_role = gtk.Label()
  416.         self.label_role.set_alignment(0, 0)
  417.         vbox.pack_start(self.label_role, False, True, 0)
  418.         vbox_progress = gtk.VBox()
  419.         vbox_progress.set_spacing(6)
  420.         self.progress = AptProgressBar()
  421.         vbox_progress.pack_start(self.progress, False, True, 0)
  422.         self.label = AptStatusLabel()
  423.         self.label._on_status_changed(None, STATUS_WAITING)
  424.         vbox_progress.pack_start(self.label, False, True, 0)
  425.         vbox.pack_start(vbox_progress, False, True, 0)
  426.         hbox.pack_start(vbox, True, True, 0)
  427.         if terminal == True:
  428.             self.expander = AptTerminalExpander()
  429.             vbox.pack_start(self.expander, False, True, 0)
  430.         self.vbox.pack_start(hbox, True, True, 0)
  431.         self._transaction = None
  432.         self._signals = []
  433.         self.set_title("")
  434.         self.realize()
  435.         self.progress.set_size_request(350, -1)
  436.         self.window.set_functions(gtk.gdk.FUNC_MOVE|gtk.gdk.FUNC_RESIZE)
  437.         if transaction != None:
  438.             self.set_transaction(transaction)
  439.         self._running = False
  440.  
  441.     def run(self, attach=False):
  442.         """Run the transaction and show the progress in the dialog.
  443.  
  444.         Keyword argument:
  445.         attach -- do not start the transaction but instead only monitor
  446.                   an already running one
  447.         """
  448.         parent = self.get_transient_for()
  449.         if attach:
  450.             self._transaction.attach(error_handler=self._on_error,
  451.                                      reply_handler=self._on_run)
  452.         else:
  453.             self._transaction.run(error_handler=self._on_error,
  454.                                   reply_handler=self._on_run)
  455.         #FIXME: Evil woraround to emulate the blocking behavior of a dialog
  456.         #       without making use of a nested main loop. Only the default
  457.         #       main loop receives D-Bus signals.
  458.         self._running = True
  459.         while self._running:
  460.             gobject.main_context_default().iteration()
  461.         return self._transaction._exit
  462.  
  463.     def _on_error(self, error):
  464.         """Stop the "emulated" loop of the progress dialog."""
  465.         self._running = False
  466.         if error.get_dbus_name() != \
  467.            "org.freedesktop.PolicyKit.Error.NotAuthorized":
  468.             raise error
  469.  
  470.     def _on_run(self):
  471.         """Show the dialog."""
  472.         self.show_all()
  473.  
  474.     def _on_role(self, transaction, role_enum):
  475.         """Show the role of the transaction in the dialog interface"""
  476.         role = get_role_localised_present_from_enum(role_enum)
  477.         self.set_title(role)
  478.         self.label_role.set_markup("<big><b>%s</b></big>" % role)
  479.  
  480.     def _setup_http_proxy(self, transaction):
  481.         try:
  482.             import gconf
  483.         except ImportError:
  484.             return
  485.         client = gconf.client_get_default()
  486.         if client.get_bool("/system/http_proxy/use_http_proxy"):
  487.             host = client.get_string("/system/http_proxy/host")
  488.             port = client.get_int("/system/http_proxy/port")
  489.             transaction.set_http_proxy("http://%s:%s/" % (host, port))
  490.  
  491.     def set_transaction(self, transaction):
  492.         """Connect the dialog to the given aptdaemon transaction"""
  493.         for sig in self._signals:
  494.             gobject.source_remove(sig)
  495.         self._signals = []
  496.         self._signals.append(
  497.             transaction.connect("role", self._on_role))
  498.         self._signals.append(
  499.             transaction.connect("medium-required", self._on_medium_required))
  500.         self._signals.append(
  501.             transaction.connect("config-file-prompt", self._on_config_file_prompt))
  502.         self._signals.append(
  503.             transaction.connect("finished", self._on_finished))
  504.         self.progress.set_transaction(transaction)
  505.         self.icon.set_transaction(transaction)
  506.         self.label.set_transaction(transaction)
  507.         if hasattr(self, "expander"):
  508.             self.expander.set_transaction(transaction)
  509.         self._transaction = transaction
  510.         if self.debconf:
  511.             self._transaction.set_debconf_frontend("gnome")
  512.         self._setup_http_proxy(transaction)
  513.  
  514.     def _on_medium_required(self, transaction, medium, drive):
  515.         dialog = AptMediumRequiredDialog(medium, drive, self)
  516.         res = dialog.run()
  517.         dialog.hide()
  518.         if res == gtk.RESPONSE_OK:
  519.             self._transaction.provide_medium(medium)
  520.         else:
  521.             self._transaction.cancel()
  522.  
  523.     def _on_config_file_prompt(self, transaction, old, new):
  524.         dialog = AptConfigFilePromptDialog(old, new, self)
  525.         res = dialog.run()
  526.         dialog.hide()
  527.         if res == gtk.RESPONSE_YES:
  528.             self._transaction.config_file_prompt_answer(old, "keep")
  529.         else:
  530.             self._transaction.config_file_prompt_answer(old, "replace")
  531.  
  532.     def _on_finished(self, transaction, status):
  533.         self._running = False
  534.  
  535. class AptMediumRequiredDialog(gtk.MessageDialog):
  536.     def __init__(self, medium, drive, parent=None):
  537.         gtk.MessageDialog.__init__(self, parent=parent,
  538.                                    type=gtk.MESSAGE_INFO,
  539.                                    buttons=gtk.BUTTONS_OK_CANCEL)
  540.         #TRANSLATORS: %s represents the name of a CD or DVD
  541.         text = _("CD/DVD '%s' is required") % medium
  542.         #TRANSLATORS: %s is the name of the CD/DVD drive
  543.         desc = _("Please insert the above CD/DVD into the drive '%s' to "
  544.                  "install software packages from the medium.") % drive
  545.         self.set_markup("<big><b>%s</b></big>\n\n%s" % (text, desc))
  546.  
  547. class AptConfigFilePromptDialog(gtk.MessageDialog):
  548.     def __init__(self, old, new, parent=None):
  549.         gtk.MessageDialog.__init__(self, parent=parent,
  550.                                    type=gtk.MESSAGE_INFO)
  551.         self.add_buttons(_("_Replace"), gtk.RESPONSE_YES,
  552.                          _("_Keep"), gtk.RESPONSE_NO)
  553.         self.set_default_response(gtk.RESPONSE_NO)
  554.         # FIMXE: use better buttons, use better text
  555.         text = _("Configuration file '%s' changed") % old
  556.         desc = _("Do you want to use the new version?")
  557.         self.set_markup("<big><b>%s</b></big>\n\n%s" % (text, desc))
  558.  
  559. class AptMessageDialog(gtk.MessageDialog):
  560.     """
  561.     Dialog for aptdaemon messages with details in an expandable text view
  562.     """
  563.     def __init__(self, enum, details=None, parent=None):
  564.         gtk.MessageDialog.__init__(self, parent=parent,
  565.                                    type=gtk.MESSAGE_INFO,
  566.                                    buttons=gtk.BUTTONS_CLOSE)
  567.         text = get_msg_string_from_enum(enum)
  568.         desc = get_msg_description_from_enum(enum)
  569.         self.set_markup("<big><b>%s</b></big>\n\n%s" % (text, desc))
  570.         self.set_details(details)
  571.  
  572.     def set_details(self, details):
  573.         if details == "":
  574.             return
  575.         #TRANSLATORS: expander label in the error dialog
  576.         expander = gtk.expander_new_with_mnemonic(_("_Details"))
  577.         expander.set_spacing(6)
  578.         scrolled = gtk.ScrolledWindow()
  579.         scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  580.         scrolled.set_shadow_type(gtk.SHADOW_ETCHED_IN)
  581.         textview = gtk.TextView()
  582.         buffer = textview.get_buffer()
  583.         buffer.insert_at_cursor(details)
  584.         scrolled.add(textview)
  585.         expander.add(scrolled)
  586.         box = self.label.get_parent()
  587.         box.add(expander)
  588.         expander.show_all()
  589.  
  590.  
  591. class AptErrorDialog(AptMessageDialog):
  592.     """
  593.     Dialog for aptdaemon errors with details in an expandable text view
  594.     """
  595.     def __init__(self, error=None, parent=None):
  596.         gtk.MessageDialog.__init__(self, parent=parent,
  597.                                    type=gtk.MESSAGE_ERROR,
  598.                                    buttons=gtk.BUTTONS_CLOSE)
  599.         text = get_error_string_from_enum(error.code)
  600.         desc = get_error_description_from_enum(error.code)
  601.         self.set_markup("<big><b>%s</b></big>\n\n%s" % (text, desc))
  602.         self.set_details(error.details)
  603.